/**
 * @(#)SimulatorNumTimer.java 2017年2月15日
 * Copyright(C) 2017 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.timer;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.math.NumberUtils;
import org.glassfish.external.statistics.annotations.Reset;
import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.domian.OnlineSimulatorNumLog;
import org.jsbd.boss.domian.SimulatorInfoVo;
import org.jsbd.boss.service.*;
import org.jsbd.boss.task.BaseTask;
import org.jsbd.boss.util.CacheKey;
import org.jsbd.boss.util.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;

/**
 * 在线模拟器数量统计
 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
 * @version 1.0.0
 */
public class SimulatorNumTimer extends BaseTask{
	public static final Logger LOGGER = LoggerFactory.getLogger(SimulatorNumTimer.class);
	
	private static final int DEVISESET_EXPIRY_TIME = PropertiesUtil.getInt("simulator_cache_time", 600000);
	
	private static final String TEMPLATE_TOTAL_CONTENT="<div style=\"font-size:120%;text-align:left;\"><b>上一次模拟器总数：{lastTotalNum}        本次模拟器总数:{nowTotalNum}    当前空闲模拟器总数:{totalUnbusy}</b></div><br>";
	private static final String TEMPLATE_DESC_CONTENT="<div style=\"font-size:120%;text-align:left;color:red\">版本：{sysVer}，模拟器减少<b>{num}</b>,上一次模拟器数量：{lastNum}，本次模拟器数量：{nowNum},当前空闲模拟器总数:{totalUnbusy}</div><br>";
	private static final String TEMPLATE_ASC_CONTENT="<div style=\"font-size:120%;text-align:left;color:green\">版本：{sysVer}，模拟器增加<b>{num}</b>,上一次模拟器数量：{lastNum}，本次模拟器数量：{nowNum},当前空闲模拟器总数:{totalUnbusy}</div><br>";
	private static final String TEMPLATE_OK_CONTENT="<div style=\"font-size:120%;text-align:left;\">版本：{sysVer}，上一次模拟器数量：{lastNum}，本次模拟器数量：{nowNum},当前空闲模拟器总数:{totalUnbusy}</div><br>";

	private static int float_num=20;
	
	@Autowired
	private RedisClient<String,Object> redisClient;
	@Autowired
	private IOnlineSimulatorNumLogService onlineSimulatorNumLogService;
	@Autowired
	private ISimulatorSysVerService simulatorSysVerService;
	@Autowired
	private IEmailSendService emailSendService;
	@Autowired
	private IMonitorConfigService monitorConfigService;

	@Resource
	private SimulatorManager simulatorManager;
	
	public void init() {
		super.setOpenFlag(PropertiesUtil.getValue("simpulator_num_open_flag", "off"));
		super.setCycleTime(PropertiesUtil.getInt("simpulator_num_cycle_time", 15000));
		super.init();
	}

	@Override
	public void run() {
		while(true){
			try{
				
				LOGGER.info("SimulatorNumTimer start work");
				
				long now = System.currentTimeMillis();
				long startTime = now - DEVISESET_EXPIRY_TIME;
				
				Map<Object,Object> simulatorMap= simulatorManager.getAllSimulatorMap();
				if(simulatorMap==null||simulatorMap.isEmpty()){
					LOGGER.info("SimulatorNum is empty");
					saveEmptyLog();
					continue;
				}
				
				Map<String,OnlineSimulatorNumLog> resultMap=new HashMap<String,OnlineSimulatorNumLog>();
				Date nowDate=new Date();
				List<OnlineSimulatorNumLog> recordList=new ArrayList<OnlineSimulatorNumLog>();
				
				for(Entry<Object, Object> entity:simulatorMap.entrySet()){
					SimulatorInfoVo simulatorInfoVo=(SimulatorInfoVo)entity.getValue();
					//超时的就不要了
					if(simulatorInfoVo.getCurrentTime()<startTime){
						continue;
					}
					String ver=simulatorInfoVo.getSysVer();
					OnlineSimulatorNumLog log=resultMap.get(ver);
					if(log==null){
						log=new OnlineSimulatorNumLog();
						log.setCreateTime(nowDate);
						recordList.add(log);
						log.setSysVer(ver);
						resultMap.put(ver, log);
					}
					
					if(!simulatorInfoVo.isBusy()){
						log.setUnbusyNum(log.getUnbusyNum()+1);
					}
					log.setTotalNum(log.getTotalNum()+1);
				}
				
				onlineSimulatorNumLogService.saveList(recordList);
				
				compareSimulatroNum(resultMap);
			}catch(Exception e){
				LOGGER.error("",e);
			}finally{
				try {
					Thread.sleep(super.getCycleTime());
				} catch (InterruptedException e) {
					LOGGER.error("",e);
				}
			}
		}
	}
	
	public void saveEmptyLog(){
		List<String> verList=simulatorSysVerService.getSysVerStringList();
		if(verList==null||verList.isEmpty()){
			return;
		}
		List<OnlineSimulatorNumLog> recordList=new ArrayList<OnlineSimulatorNumLog>();
		Date nowDate=new Date();
		for(String ver:verList){
			OnlineSimulatorNumLog info=new OnlineSimulatorNumLog();
			info.setTotalNum(0);
			info.setSysVer(ver);
			info.setUnbusyNum(0);
			info.setCreateTime(nowDate);
			recordList.add(info);
		}
		
		onlineSimulatorNumLogService.saveList(recordList);
		
		compareSimulatroNum(new HashMap<String,OnlineSimulatorNumLog>());
		
	}
	
	private void compareSimulatroNum(Map<String,OnlineSimulatorNumLog> resultMap){
		Map<String, String>  dataMap=monitorConfigService.getAllMonitorConfigMap();
		String configFloatNum=dataMap.get("float_simulator_num");
		if(NumberUtils.isNumber(configFloatNum)){
			float_num=Integer.valueOf(configFloatNum);
		}
		
		List<String> verList=simulatorSysVerService.getSysVerStringList();
		if(verList==null||verList.isEmpty()){
			return;
		}
		
		Map<String,OnlineSimulatorNumLog> lastMap=(Map<String,OnlineSimulatorNumLog>)redisClient.get(CacheKey.LAST_SIMULATOR_NUM_KEY);
		if(lastMap==null){
			redisClient.put(CacheKey.LAST_SIMULATOR_NUM_KEY,resultMap);
			return;
		}
		
		List<String> alarmList=new ArrayList<String>();
		
		boolean isSave=false;
		
		int lastAllNum=0;
		int nowAllNum=0;
		int unbusyAllNum=0;
		for(String sysVer:verList){
			OnlineSimulatorNumLog lastNumLog=lastMap.get(sysVer);
			OnlineSimulatorNumLog nowNumLog=resultMap.get(sysVer);
			
			int lastTotalNum=0;
			int nowTotalNum=0;
			int unbusyNum=0;
			if(lastNumLog!=null){
				lastTotalNum=lastNumLog.getTotalNum();
			}
			if(nowNumLog!=null){
				nowTotalNum=nowNumLog.getTotalNum();
				if(nowNumLog.getUnbusyNum()!=null){
					unbusyNum=nowNumLog.getUnbusyNum();
				}
			}
			
			lastAllNum+=lastTotalNum;
			nowAllNum+=nowTotalNum;
			unbusyAllNum+=unbusyNum;
			
			int remainNum=lastTotalNum-nowTotalNum;
			if(Math.abs(remainNum)>=float_num){
				createAlarmInfo(lastTotalNum,nowTotalNum,remainNum,sysVer,alarmList,unbusyNum);
				lastMap.put(sysVer, nowNumLog);
				isSave=true;
			}else{
				String alarmContent=TEMPLATE_OK_CONTENT.replace("{sysVer}", sysVer)
						.replace("{lastNum}", lastTotalNum+"")
						.replace("{nowNum}", nowTotalNum+"")
				        .replace("{nowNum}", nowTotalNum+"")
				        .replace("{totalUnbusy}", unbusyNum+"");
				alarmList.add(alarmContent);
			}
		}
		
		if(isSave){
			redisClient.put(CacheKey.LAST_SIMULATOR_NUM_KEY,lastMap);
			String content=TEMPLATE_TOTAL_CONTENT.replace("{lastTotalNum}", ""+lastAllNum)
					.replace("{nowTotalNum}", ""+nowAllNum)
					.replace("{totalUnbusy}", ""+unbusyAllNum);
			alarmList.add(0, content);
			sendEmail(alarmList);
		}
		
	}

	
	private void createAlarmInfo(int lastTotalNum,int nowTotalNum,int remainNum,
			String sysVer,List<String> alarmList,int unbusyNum){
		String alarmContent="";
		
		//说明下降了
		if(remainNum>0){
			alarmContent=TEMPLATE_DESC_CONTENT.replace("{num}",remainNum+"")
					.replace("{sysVer}", sysVer)
					.replace("{lastNum}", lastTotalNum+"")
					.replace("{nowNum}", nowTotalNum+"")
					.replace("{totalUnbusy}", unbusyNum+"");
			
		}else{
		    alarmContent=TEMPLATE_ASC_CONTENT.replace("{num}", Math.abs(remainNum)+"")
					.replace("{sysVer}", sysVer)
					.replace("{lastNum}", lastTotalNum+"")
					.replace("{nowNum}", nowTotalNum+"")
					.replace("{totalUnbusy}", unbusyNum+"");
		}
		
		alarmList.add(alarmContent);
	}
	
	/**
	 * 
	 * 发送邮件
	 * @author <a href="mailto:zhouchao@zhexinit.com" >周超</a>
	 * @param alarmList
	 */
	private void sendEmail(List<String> alarmList){
		StringBuilder content=new StringBuilder();
		for(String alarm:alarmList){
			content.append(alarm);
		}
		try {
			//emailSendService.sendEmailToSysAccount("模拟器数量变动通知", content.toString(), null);
			emailSendService.sendEmailToSysAccountGroup("模拟器数量变动通知", content.toString(), null, "Y2");
		} catch (IOException e) {
			LOGGER.error("sendEmailToSysAccount errro",e);
		}
	}
	
	
}
